package com.liuya.safe.policy.controller;

import com.liuya.base.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.servlet.ServletException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.liuya.db.DBPower;
import com.liuya.db.DBView;
import com.liuya.db.TableView;

import com.google.gson.Gson;


/**
 * @author liuya
 * @date 20160926
 */
@Controller
@Api(value = "公共访问", description = "公共访问")
@RequestMapping(value = "utils")
public class UtilController extends BaseController {

    private static final Log log = LogFactory.getLog(UtilController.class);

    @ApiOperation(value = "javabean属性")
//    @RequiresPermissions("sys.queryPolicy.getJavaBeanProperties")
    @RequestMapping(value = "/getJavaBeanProperties")
    public void getJavaBeanProperties(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap) throws IOException, ServletException {
        String oper = req.getParameter("oper");
        getJavaBeanProperties(req, rep);
        return;
    }

    @ApiOperation(value = "数据源名称")
//    @RequiresPermissions("sys.queryPolicy.getAppDsNames")
    @RequestMapping(value = "/getAppDsNames")
    public void getAppDsNames(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap) throws IOException {
        String oper = req.getParameter("oper");
        getAppDsNames(req, rep);
        return;
    }

    @ApiOperation(value = "加载数据库表")
//    @RequiresPermissions("sys.queryPolicy.loadDbView")
    @RequestMapping(value = "/loadDbView")
    public void loadDbView(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap) throws IOException {
        String oper = req.getParameter("oper");
        loadDbView(req, rep);
        return;
    }

    @ApiOperation(value = "获取表列")
//    @RequiresPermissions("sys.queryPolicy.getTableColumns")
    @RequestMapping(value = "/getTableColumns")
    public void getTableColumns(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap) throws IOException {
        String oper = req.getParameter("oper");
        getTableColumns(req, rep);
        return;
    }


    private void getTableColumns(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // get table or view definition
        String schema = req.getParameter("schema");
        String tableName = req.getParameter("tableName");
        String dsName = req.getParameter("dsName");
        // String queryId=req.getParameter( "queryId" );
        String alias = req.getParameter("alias");

        TableView tableView = DBView.getTable(dsName, schema, tableName);

        responseTableDefinition(resp, tableView, alias);
    }

    private void responseTableDefinition(HttpServletResponse resp, TableView tableView, String alias) throws IOException {
        Gson gson = new Gson();
        String json = gson.toJson(tableView);
        // append alias to json
        json = json.substring(0, json.lastIndexOf('}')) + ",\"alias\":\"" + alias + "\"}";

        if (log.isDebugEnabled()) {
            log.debug("The json is:" + json);
        }

        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter pw = resp.getWriter();
        pw.write(json);
        pw.flush();
    }

    private void getAppDsNames(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Collection dsNames = DBPower.getDsNames();
        ArrayList appDsNames = new ArrayList(dsNames.size());

        for (Iterator iterator = dsNames.iterator(); iterator.hasNext();) {
            String name = (String) iterator.next();
            if (!name.equals("safe")) {
                appDsNames.add(name);
            }
        }

        Gson gson = new Gson();
        String json = gson.toJson(appDsNames);

        if (log.isDebugEnabled()) {
            log.debug("The json is:" + json);
        }

        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter pw = resp.getWriter();
        // pw.write( "\"appDsNames\":" );
        pw.write(json);
        pw.flush();
    }

    private void loadDbView(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String dsName = req.getParameter("dsName");
        String[] allSchemas = DBView.getSchemas(dsName);
        String defaultSchema = DBView.getDefaultSchema(dsName);

        int id = 0;
        resp.setContentType("application/json;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("[\r\n");
        for (int i = 0; i < allSchemas.length; i++) {
            String schema = allSchemas[i];
            boolean isDefault = defaultSchema.equals(schema);
            String[] tableNames = DBView.getTableNames(dsName, schema);
            String[] viewNames = DBView.getViewNames(dsName, schema);

            if (isDefault) {
                schema = schema + " [Default]";
            }

            if (i != 0) {
                writer.write(",\r\n");
            }
            writer.write("\t{id:" + id++ + ", iconSkin: 'schema', name:'" + schema + "', nodes:[\r\n");

            // if it's default schema, keep schema attribute value as blank
            if (isDefault) {
                schema = "";
            }

            writer.write("\t\t{id:" + id++ + ", iconSkin: 'tables', name:'Tables', nodes:[\r\n");
            id = write(writer, tableNames, schema, "table", id);
            writer.write("\t\t]},\r\n");

            writer.write("\t\t{id:" + id++ + ", iconSkin: 'views', name:'Views', nodes:[\r\n");
            id = write(writer, viewNames, schema, "view", id);
            writer.write("\t\t]}\r\n");

            writer.write("\t]}");
        }
        writer.write("]");
        writer.flush();
    }

    private int write(PrintWriter writer, String[] names, String schema, String type, int id) {
        for (int i = 0; i < names.length; i++) {
            String name = names[i];

            if (i != 0) {
                writer.write(",\r\n");
            }
            writer.write("\t\t\t{id:" + id++ + ", iconSkin: 'dbObject', name:'" + name + "', type:'" + type + "', schema:'" + schema + "'}");
        }

        return id;
    }

    private void getJavaBeanProperties(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        String clazz = req.getParameter("clazz");
        Class c;
        Properties prop = new Properties();
        try {
            c = Class.forName(clazz);
            Field[] fields = c.getDeclaredFields();
            int length = fields.length;
            String[] properties = new String[length];
            String[] javaTypes = new String[length];

            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                properties[i] = field.getName();
                javaTypes[i] = field.getType().getName();
            }

            prop.setJavaTypes(javaTypes);
            prop.setProperties(properties);
        } catch (ClassNotFoundException e) {
            prop.setErrorMsg(e.toString());
        }

        Gson gson = new Gson();
        String json = gson.toJson(prop);

        if (log.isDebugEnabled()) {
            log.debug("The json is:" + json);
        }
        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter pw = resp.getWriter();
        pw.write(json);
        pw.flush();
    }

    class Properties {
        private String errorMsg = "";
        private String[] properties;
        private String[] javaTypes;

        public String getErrorMsg() {
            return errorMsg;
        }

        public void setErrorMsg(String errorMsg) {
            this.errorMsg = errorMsg;
        }

        public String[] getProperties() {
            return properties;
        }

        public void setProperties(String[] properties) {
            this.properties = properties;
        }

        public String[] getJavaTypes() {
            return javaTypes;
        }

        public void setJavaTypes(String[] javaTypes) {
            this.javaTypes = javaTypes;
        }
    }
}

